#include "threadPool.h"
#include "netdisk.h"
#define rootdir "/home/wsz/CloudDisk/CloudDisk_v2.0/server/test"
void *threadFunc(void * arg){
    threadPool_t * pthreadPool = (threadPool_t *)arg;
    while(1){
        // 取出任务
        pthread_mutex_lock(&pthreadPool->mutex);
        while(pthreadPool->taskQueue.queueSize == 0 && pthreadPool->exitflag == 0){
            pthread_cond_wait(&pthreadPool->cond,&pthreadPool->mutex);
        }
        if(pthreadPool->exitflag == 1){
            pthread_mutex_unlock(&pthreadPool->mutex);
            pthread_exit(NULL);
        }
        printf("worker got a task!\n");
        int netfd = pthreadPool->taskQueue.pfront->fd;
        Dequeue(&pthreadPool->taskQueue);
        pthread_mutex_unlock(&pthreadPool->mutex);
        
        // 不使用transfile
        // transFile(netfd);
        
        // 客户端发送用户名和密码，服务端接收之后登入
        char name[128] = {0};
        char buf[256] = {0};

        // 用返回值记录操作的错误信息，0代表没有出错，-1代表出错
        int ret;
        
        // 用于验证用户登录的过程！！！
        // 借用 Linux 操作系统的用户管理系统，进行用户的登录
        login(netfd,  name);
        LOG_CHECK("login", name);
        // 得到用户名后，初始化目录栈
        Stack_t dir; // 定义一个目录栈 dir 
        bzero(&dir, sizeof(dir)); // 并将其清零
        // 构造用户的初始目录路径（/home/<username>）
        sprintf(buf, rootdir,name);
        // 将初始目录路径压入目录栈
        push(&dir, buf);

        while(1){
            // 每次执行新操作前把当前工作目录返回给客户端
            tran_t working_dir; // 用于存储当前工作目录信息
            bzero(&working_dir, sizeof(tran_t));
            // 调用 travel_stack 函数将目录栈的内容转换为字符串存储到 working_dir.data中
            //     travel_stack函数通常用于遍历栈结构并输出栈中的元素（后进先除）
            travel_stack(dir, working_dir.data); 
            working_dir.length = strlen(working_dir.data);

            // 将当前工作目录信息发送给客户端
            send(netfd, &working_dir, sizeof(working_dir.length)+
                 working_dir.length, MSG_NOSIGNAL);
            
            // 接收客户端发送的命令和参数
            int operat = 0; // 存储客户端发送的操作类型
            int arg_length; // 存储客户端发送的参数长度

            // 调用recvn函数接收客户端发送的命令类型
            ret = recvn(netfd, &operat, sizeof(int));
            if(ret == 0){ // 返回值为0，表示客户端关闭连接！！！！
                break;
            }
            printf("operate = %d\n", operat);
            // 接收客户端发送的参数长度
            ret = recvn(netfd, &arg_length, sizeof(int));

            // 为参数分配相应长度的空间，用于存储参数
            char* arg = (char*)malloc(arg_length + 1);
            //ERROR_CHECK(arg, NULL,"malloc");
            
            // 接收参数内容并确保字符串以空字符结尾！！
            ret = recvn(netfd, arg, arg_length);

            arg[arg_length] = '\0';

            if(arg[0] != '\0'){
                arg[arg_length - 1] = '\0';
            }
            // arg_length：命令参数的长度  arg：命令参数
            // e.g. cd test     arg_length = 4  arg = test dir = /home/<username>
            printf("arg_length = %ld, arg = %s\n", strlen(arg), arg);

            // 根据参数类型执行不同操作
            switch(operat){
            case 0:
                ret = cdFunc(arg, &dir);// 改变当前工作牡蛎
                print_stack(dir); // 打印目录栈内容
                LOG_CHECK("cd", arg); // 记录日志
                func_error_check(ret, netfd); // 检查错误
                break;

            case 1:
                ls_fun(arg, netfd, &dir); 
                LOG_CHECK("ls", arg);
                break;

            case 2:
                ret = putsTextFunc(arg, netfd, dir);
                LOG_CHECK("puts", arg);
                break;

            case 3:
                ret = getsTextFunc(arg, netfd, dir);
                LOG_CHECK("gets", arg);
                break;

            case 4:
                ret = removeFunc(arg, dir);
                LOG_CHECK("remove", arg);
                func_error_check(ret, netfd);
                break;

            case 5:
                ret = pwdFunc(dir, netfd);
                LOG_CHECK("pwd", arg);
                break;

            case 6:
                ret = mkdirFunc(arg, dir);
                LOG_CHECK("mkdir", arg);
                func_error_check(ret, netfd);
                break;

            case 7:
                ret = rmdirFunc(arg, dir);
                LOG_CHECK("rmdir", arg);
                func_error_check(ret, netfd);
                break;

            default:
                send(netfd, &ret, sizeof(int), MSG_NOSIGNAL);
            }
            free(arg); // 释放动态分配的内存
        }
        destroy_stack(&dir); // 销毁目录栈
        close(netfd);
    }
}
//void unlock(void *arg){
//    threadPool_t * pthreadPool = (threadPool_t *)arg;
//    pthread_mutex_unlock(&pthreadPool->mutex);
//}
//void *threadFunc(void * arg){
//    threadPool_t * pthreadPool = (threadPool_t *)arg;
//    while(1){
//        // 取出任务
//        int netfd;
//        pthread_mutex_lock(&pthreadPool->mutex);
//        pthread_cleanup_push(unlock,pthreadPool);
//        while(pthreadPool->taskQueue.queueSize == 0){
//            pthread_cond_wait(&pthreadPool->cond,&pthreadPool->mutex);
//        }
//        printf("worker got a task!\n");
//        netfd = pthreadPool->taskQueue.pfront->fd;
//        Dequeue(&pthreadPool->taskQueue);
//        //pthread_mutex_unlock(&pthreadPool->mutex);
//        pthread_cleanup_pop(1);
//        
//        transFile(netfd);
//        close(netfd);
//    }
//}
int makeWorker(threadPool_t *pthreadPool){
    for(int i = 0; i < pthreadPool->workerNum; ++i){
        pthread_create(&pthreadPool->tidArr[i],NULL,threadFunc,pthreadPool);
    }
    return 0;
}
